using System;
using NUnit.Framework;
using TDUnit.Common.TestData;
using TDUnit.Common.Resolver;

namespace TDUnit.Tests
{
    [TestFixture]
    public class DependencyResolverTests
    {
        private const string valueToResolve = @"$(TableName.RowName.ColumnName)";

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateResolverWithNullDataSetThrowsException()
        {
            new DependencyResolver(null);
        }

        [Test]
        public void ShouldResolveReturnsFalseForEmptyString()
        {
            var resolver = new DependencyResolver(new TestData());
            Assert.IsFalse(resolver.ShouldResolve(string.Empty));
        }

        [Test]
        public void ShouldResolveReturnsTrueForValueThatShouldBeResolved()
        {
            var resolver = new DependencyResolver(new TestData());
            Assert.IsTrue(resolver.ShouldResolve(valueToResolve));
        }

        [Test]
        public void GetTableNameShouldReturnEmptyStringIfNoMatch()
        {
            Assert.AreEqual(string.Empty, DependencyResolver.ExtractTableName("NoTableValueHere"));
        }

        [Test]
        public void GetTableNameShouldReturnTableNameExtractedFromValue()
        {
            Assert.AreEqual("TableName", DependencyResolver.ExtractTableName(valueToResolve));
        }

        [Test]
        public void GetRowNameShouldReturnEmptyStringIfNoMatch()
        {
            Assert.AreEqual(string.Empty, DependencyResolver.ExtractRowName("NoRowNameHere"));
        }

        [Test]
        public void GetRowNameShouldReturnRowNameExtractedFromValue()
        {
            Assert.AreEqual("RowName", DependencyResolver.ExtractRowName(valueToResolve));
        }

        [Test]
        public void GetColumnNameShouldReturnEmptyStringIfNoMatch()
        {
            Assert.AreEqual(string.Empty, DependencyResolver.ExtractColumnName("NoColumnNameHere"));
        }

        [Test]
        public void GetColumnNameShouldReturnColumnNameExtractedFromValue()
        {
            Assert.AreEqual("ColumnName", DependencyResolver.ExtractColumnName(valueToResolve));
        }

        [Test]
        [ExpectedException(typeof(DependencyResolverException))]
        public void ResolveShouldThrowExceptionIfDataSetIsEmpty()
        {
            new DependencyResolver(new TestData()).Resolve(valueToResolve);
        }

        [Test]
        [ExpectedException(typeof(DependencyResolverException))]
        public void ResolvingValueWithTableThatDoesNotExistInDataSetThrowsException()
        {
            var ds = new TestData();
            ds.AddTable("TableThatIsNotInDataSet", "SomePKColumn");
            new DependencyResolver(ds).Resolve(valueToResolve);
        }

        [Test]
        [ExpectedException(typeof(DependencyResolverException))]
        public void ResolvingValueWithRowThatDoesNotExistInTableThrowsException()
        {
            var ds = new TestData();
            ds.AddTable("TableName", "SomePKColumn").AddRow(new PrimaryKeyColumn("SomePKColumnName"), "RowThatIsNotInDataSet");
            new DependencyResolver(ds).Resolve(valueToResolve);
        }

        [Test]
        [ExpectedException(typeof(DependencyResolverException))]
        public void ResolvingValueWithColumnThatDoesNotExistInRowThrowsException()
        {
            var ds = new TestData();
            ds.AddTable("TableName", "SomePKColumn").AddRow(new PrimaryKeyColumn("SomePKColumnName"), "RowName").AddColumn("ColumnThatIsNotInDataSet", "", null);
            new DependencyResolver(ds).Resolve(valueToResolve);
        }

        [Test]
        public void ResolvingValueReturnsDependedOnColumn()
        {
            var ds = new TestData();
            var dependedOnColumn = ds.AddTable("TableName", "SomePKColumn").AddRow(new PrimaryKeyColumn("SomePKColumnName"), "RowName").AddColumn("ColumnName", "ColumnValue", null);
            var resolverReturn = new DependencyResolver(ds).Resolve(valueToResolve);

            Assert.AreSame(dependedOnColumn, resolverReturn);
        }
    }
}